<script setup lang="ts">
import { nextTick, onMounted, reactive, ref, toRefs } from 'vue';

import { StorageManager } from '@vben-core/shared/cache';

import MapboxLanguage from '@mapbox/mapbox-gl-language';
import {
  ElAutoResizer,
  ElCol,
  ElDescriptions,
  ElDescriptionsItem,
  ElDialog,
  ElDivider,
  ElRow,
  ElScrollbar,
  ElTableV2,
} from 'element-plus';
import mapboxgl from 'mapbox-gl';

import { vectorServiceApi } from '#/api';
import layerStyleProperties from '#/assets/style/layer-style-properties';

import 'element-plus/theme-chalk/el-loading.css';

const props = defineProps({
  currentMvtData: {
    default: () => ({}),
    type: Object,
  },
  isDialogShow: {
    default: false,
    type: Boolean,
  },
  dataName: {
    default: 'No data has been selected!',
    type: String,
  },
});

const emits = defineEmits(['closePreviewDialog', 'deleteGeoData']);

const storageManager = new StorageManager({
  prefix: '',
  storageType: 'sessionStorage',
});

mapboxgl.accessToken =
  'pk.eyJ1IjoibmluamFhIiwiYSI6ImNsYXYzd3JwaDAyMGwzdm44ZmI3M212eHQifQ.h_dGMMOvQXNfmheNd0_j8A';
type PreviewData = {
  bbox: Array<number>;
  center: Array<number>;
  fileId: string;
  geoType: string;
  id: string;
  name: string;
  ownerCount: string;
  ptName: string;
  publisher: string;
  publishTime: string;
  type: string;
  url: string;
};

const { isDialogShow, currentMvtData } = toRefs(props);
// console.log(props.currentMvtData);
const scene = reactive({
  map: null as any,
});
const preview = reactive({
  data: {} as PreviewData,
});
const isloading = ref(true);
const isTableloading = ref(true);
const features = reactive({
  data: [] as any,
});
const publisher = storageManager.getItem('username');
const title = ref([] as any);
const rowheight = ref(40);
const bboxTop = ref();
const bboxBottom = ref();
const bboxLeft = ref();
const bboxRight = ref();

// 初始化地图
const initMap = () => {
  return new Promise((resolve) => {
    scene.map = new mapboxgl.Map({
      container: 'map', // container ID
      style: {
        version: 8,
        sources: {
          localTiles: {
            type: 'raster',
            tiles: [
              'http://32.12.195.125/basemap-server/tile?x={x}&y={y}&z={z}',
            ], // 本地瓦片服务 URL
            tileSize: 256,
            minzoom: 0,
            maxzoom: 9,
          },
        },
        layers: [
          {
            id: 'localTilesLayer',
            type: 'raster',
            source: 'localTiles',
            minzoom: 0,
            maxzoom: 9,
          },
        ],
      },
      center: [116.4, 39.9], // starting position [lng, lat]
      zoom: 8, // starting zoom
    });
    scene.map.addControl(
      new MapboxLanguage({
        defaultLanguage: 'zh-Hans',
      }),
    );
    scene.map.addControl(
      new mapboxgl.NavigationControl({
        visualizePitch: true,
      }),
    );
    // 添加比例尺
    const scale = new mapboxgl.ScaleControl({
      maxWidth: 120,
    });
    scene.map.addControl(scale);
    scale.setUnit('metric');

    // 添加全局缩放
    scene.map.addControl(new mapboxgl.FullscreenControl());

    // 添加定位控件
    scene.map.addControl(
      new mapboxgl.GeolocateControl({
        positionOptions: {
          enableHighAccuracy: true,
        },
        trackUserLocation: true,
      }),
    );
    scene.map.on('load', () => {
      resolve(true);
    });
  });
};
const closePreviewDialog = () => {
  emits('closePreviewDialog');
};

const getPaintType = () => {
  switch (preview.data.geoType) {
    case 'LINESTRING':
    case 'MULTILINESTRING': {
      return 'line';
    }
    case 'MULTIPOINT':
    case 'POINT': {
      return 'circle';
    }
    case 'MULTIPOLYGON':
    case 'POLYGON': {
      return 'fill';
    }
    // No default
  }
};
const previewDataInMap = () => {
  return new Promise((resolve) => {
    const geoType = getPaintType() as string;
    const paint_new = structuredClone(layerStyleProperties[geoType].paint);
    const source_id = `preview_source_${preview.data.id}`;
    const source_url = preview.data.url;
    delete paint_new[`${geoType}-pattern`];
    if (preview.data.type === 'geojson') {
      scene.map.addSource(source_id, {
        type: 'geojson',
        data: source_url,
      });
    } else if (preview.data.type === 'vector') {
      scene.map.addSource(source_id, {
        type: 'vector',
        tiles: [source_url],
      });
    }

    // console.log(scene.map.getSource("preview_source_" + geoId.value))
    const layerOption = {
      id: `preview_layer_${preview.data.id}`,
      type: geoType,
      layout: structuredClone(layerStyleProperties[geoType].layout), // 防止同类型图层样式改变间影响
      // filter: ["all"],
      source: source_id,
      'source-layer': preview.data.ptName, // source-layer要和pg中的表名对应
      paint: paint_new,
    } as any;
    if (preview.data.type === 'geojson') {
      delete layerOption['source-layer'];
    }
    if (geoType !== 'symbol') {
      layerOption.paint[`${geoType}-color`] =
        `#${Math.random().toString(16).slice(2, 8)}`;
    }
    scene.map.addLayer(layerOption);
    scene.map.fitBounds(preview.data.bbox, {
      padding: { top: 10, bottom: 25, left: 15, right: 5 },
    });
    resolve('资源加载完毕');
  });
};

onMounted(() => {
  nextTick(async () => {
    await initMap();
    preview.data = currentMvtData as any;
    bboxTop.value = preview.data.bbox[3];
    bboxBottom.value = preview.data.bbox[1];
    bboxLeft.value = preview.data.bbox[0];
    bboxRight.value = preview.data.bbox[2];
    isloading.value = false;
    await previewDataInMap();
    // getDetails()
    if (preview.data.type === 'geojson') {
      vectorServiceApi.getAtrrsFromGeojson(preview.data.id).then((response) => {
        if (response) {
          features.data = response;
          for (const keyV in response[0]) {
            title.value.push({
              key: keyV,
              dataKey: keyV,
              title: keyV,
              width: 120,
            });
          }
          isTableloading.value = false;
        }
      });
    } else {
      vectorServiceApi.getAtrr(preview.data.ptName).then((response) => {
        if (response) {
          features.data = response;
          for (const keyV in response[0]) {
            title.value.push({
              key: keyV,
              dataKey: keyV,
              title: keyV,
              width: 120,
            });
          }
          isTableloading.value = false;
        }
      });
    }
  });
});
</script>

<template>
  <div>
    <ElDialog
      v-model="isDialogShow"
      align-center
      @close="closePreviewDialog"
      destroy-on-close
    >
      <template #header="{ titleId, titleClass }">
        <div class="my-header">
          <h2 :id="titleId" :class="titleClass" style="font-size: 20px">
            矢量服务资源预览
          </h2>
          <!-- <div>
            <el-button type="primary" @click="closePreviewDialog" size="large" text round>x</el-button>
          </div> -->
        </div>
      </template>
      <ElDivider style="margin-top: 0; margin-bottom: 10px" />
      <ElRow class="all">
        <ElCol :span="8">
          <ElRow style="width: 100%; height: 40%; padding: 0">
            <div id="map"></div>
          </ElRow>
          <ElDivider style="margin-top: 10px; margin-bottom: 20px" />

          <ElRow style="width: 100%; height: 50%">
            <ElScrollbar style="width: 100%">
              <ElDescriptions
                v-loading="isloading"
                element-loading-text="正在加载数据信息..."
                title="数据信息(ReadOnly)"
                size="large"
                :column="1"
                border
              >
                <ElDescriptionsItem align="center">
                  <template #label>
                    <div class="cell-item">数据名称</div>
                  </template>
                  {{ preview.data.name }}
                </ElDescriptionsItem>
                <ElDescriptionsItem align="center">
                  <template #label>
                    <div class="cell-item">类型</div>
                  </template>
                  {{ preview.data.type }}
                </ElDescriptionsItem>
                <ElDescriptionsItem align="center">
                  <template #label>
                    <div class="cell-item">数据类型</div>
                  </template>
                  {{ preview.data.geoType }}
                </ElDescriptionsItem>
                <ElDescriptionsItem align="center">
                  <template #label>
                    <div class="cell-item">空间范围</div>
                  </template>
                  Top:
                  {{ bboxTop }}<br />
                  Left:
                  {{ bboxLeft }}&nbsp;&nbsp; Right: {{ bboxRight }}<br />
                  Bottom:
                  {{ bboxBottom }}
                </ElDescriptionsItem>
                <ElDescriptionsItem align="center">
                  <template #label>
                    <div class="cell-item">发布者</div>
                  </template>
                  {{ publisher }}
                </ElDescriptionsItem>

                <ElDescriptionsItem align="center">
                  <template #label>
                    <div class="cell-item">数据拥有者</div>
                  </template>
                  {{ preview.data.ownerCount }}
                </ElDescriptionsItem>
              </ElDescriptions>
            </ElScrollbar>
          </ElRow>
        </ElCol>
        <ElDivider direction="vertical" />
        <ElCol :span="16">
          <div class="rightCon">
            <h3 style="margin: 0; font-size: medium; color: black">属性表</h3>
            <div
              class="tableCon"
              v-loading="isTableloading"
              element-loading-text="正在加载属性表..."
            >
              <ElAutoResizer>
                <template #default="{ height, width }">
                  <ElTableV2
                    :row-height="rowheight"
                    :columns="title"
                    :data="features.data"
                    :width="width"
                    :height="height"
                    fixed
                  />
                </template>
              </ElAutoResizer>
            </div>
          </div>
        </ElCol>
      </ElRow>
    </ElDialog>
  </div>
</template>

<style scoped>
/* 隐藏logo */
:deep(.mapboxgl-ctrl-logo) {
  display: none !important;
}

:deep(.mapboxgl-ctrl-bottom-right) {
  display: none !important;
}

#map {
  width: 100%;
  height: 100%;
  padding: 0;
  margin: 0;
  border: 1 px solid black;
  border-radius: 10px;
}

.all {
  position: relative;
  box-sizing: border-box;
  display: flex;
  flex-flow: row nowrap;
  justify-content: center;
  width: auto;
  height: 70vh;
  padding-top: 5px;
  border: 1 px solid;
}

.cell-item {
  display: inline-block;
  width: 70px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

:deep(.el-dialog) {
  width: 75vw;

  /* height: auto; */
  border-radius: 20px;
}

.rightCon {
  width: 98%;
  height: 100%;
  padding-left: 20px;

  /* background-color: aqua; */
}

.el-tab-paneCon {
  width: 100%;
  height: 100%;
}

.my-header {
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: space-between;
  height: 20px;
  padding-top: 5px;
  padding-bottom: 5px;
  padding-left: 20px;
  font-size: 30px;
}

:deep(.el-dialog__body) {
  padding-top: 5px;
  padding-bottom: 0;
}

:deep(.el-dialog__footer) {
  padding: 5px;
}

.titleClass {
  font-size: 30px;
}

:deep(.el-descriptions) {
  width: 100%;
}

.el-divider--vertical {
  height: 100%;
  margin-left: 10px;
}

.el-descriptions {
  max-height: 40vh;
}

.tableCon {
  width: 98%;
  height: 64vh;
}

:deep(.el-table-v2__row-cell) {
  font-size: smaller;
}

:deep(.el-table-v2__header-cell) {
  height: 125%;
  font-size: small;
}
</style>
